home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gsfunc0.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  12.7 KB  |  472 lines

  1. /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gsfunc0.c,v 1.3 2000/09/19 19:00:28 lpd Exp $ */
  20. /* Implementation of FunctionType 0 (Sampled) Functions */
  21. #include "math_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsfunc0.h"
  25. #include "gsparam.h"
  26. #include "gxfarith.h"
  27. #include "gxfunc.h"
  28.  
  29. typedef struct gs_function_Sd_s {
  30.     gs_function_head_t head;
  31.     gs_function_Sd_params_t params;
  32. } gs_function_Sd_t;
  33.  
  34. /* GC descriptor */
  35. private_st_function_Sd();
  36. private
  37. ENUM_PTRS_WITH(function_Sd_enum_ptrs, gs_function_Sd_t *pfn)
  38. {
  39.     index -= 3;
  40.     if (index < st_data_source_max_ptrs)
  41.     return ENUM_USING(st_data_source, &pfn->params.DataSource,
  42.               sizeof(pfn->params.DataSource), index);
  43.     return ENUM_USING_PREFIX(st_function, st_data_source_max_ptrs);
  44. }
  45. ENUM_PTR3(0, gs_function_Sd_t, params.Encode, params.Decode, params.Size);
  46. ENUM_PTRS_END
  47. private
  48. RELOC_PTRS_WITH(function_Sd_reloc_ptrs, gs_function_Sd_t *pfn)
  49. {
  50.     RELOC_PREFIX(st_function);
  51.     RELOC_USING(st_data_source, &pfn->params.DataSource,
  52.         sizeof(pfn->params.DataSource));
  53.     RELOC_PTR3(gs_function_Sd_t, params.Encode, params.Decode, params.Size);
  54. }
  55. RELOC_PTRS_END
  56.  
  57. /* Define the maximum plausible number of inputs and outputs */
  58. /* for a Sampled function. */
  59. #define max_Sd_m 16
  60. #define max_Sd_n 16
  61.  
  62. /* Get one set of sample values. */
  63. #define SETUP_SAMPLES(bps, nbytes)\
  64.     int n = pfn->params.n;\
  65.     byte buf[max_Sd_n * ((bps + 7) >> 3)];\
  66.     const byte *p;\
  67.     int i;\
  68. \
  69.     data_source_access(&pfn->params.DataSource, offset >> 3,\
  70.                nbytes, buf, &p)
  71.  
  72. private int
  73. fn_gets_1(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  74. {
  75.     SETUP_SAMPLES(1, ((offset & 7) + n + 7) >> 3);
  76.     for (i = 0; i < n; ++i) {
  77.     samples[i] = (*p >> (~offset & 7)) & 1;
  78.     if (!(++offset & 7))
  79.         p++;
  80.     }
  81.     return 0;
  82. }
  83. private int
  84. fn_gets_2(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  85. {
  86.     SETUP_SAMPLES(2, (((offset & 7) >> 1) + n + 3) >> 2);
  87.     for (i = 0; i < n; ++i) {
  88.     samples[i] = (*p >> (6 - (offset & 7))) & 3;
  89.     if (!((offset += 2) & 7))
  90.         p++;
  91.     }
  92.     return 0;
  93. }
  94. private int
  95. fn_gets_4(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  96. {
  97.     SETUP_SAMPLES(4, (((offset & 7) >> 2) + n + 1) >> 1);
  98.     for (i = 0; i < n; ++i) {
  99.     samples[i] = ((offset ^= 4) & 4 ? *p >> 4 : *p++ & 0xf);
  100.     }
  101.     return 0;
  102. }
  103. private int
  104. fn_gets_8(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  105. {
  106.     SETUP_SAMPLES(8, n);
  107.     for (i = 0; i < n; ++i) {
  108.     samples[i] = *p++;
  109.     }
  110.     return 0;
  111. }
  112. private int
  113. fn_gets_12(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  114. {
  115.     SETUP_SAMPLES(12, (((offset & 7) >> 2) + 3 * n + 1) >> 1);
  116.     for (i = 0; i < n; ++i) {
  117.     if (offset & 4)
  118.         samples[i] = ((*p & 0xf) << 8) + p[1], p += 2;
  119.     else
  120.         samples[i] = (*p << 4) + (p[1] >> 4), p++;
  121.     offset ^= 4;
  122.     }
  123.     return 0;
  124. }
  125. private int
  126. fn_gets_16(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  127. {
  128.     SETUP_SAMPLES(16, n * 2);
  129.     for (i = 0; i < n; ++i) {
  130.     samples[i] = (*p << 8) + p[1];
  131.     p += 2;
  132.     }
  133.     return 0;
  134. }
  135. private int
  136. fn_gets_24(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  137. {
  138.     SETUP_SAMPLES(24, n * 3);
  139.     for (i = 0; i < n; ++i) {
  140.     samples[i] = (*p << 16) + (p[1] << 8) + p[2];
  141.     p += 3;
  142.     }
  143.     return 0;
  144. }
  145. private int
  146. fn_gets_32(const gs_function_Sd_t * pfn, ulong offset, uint * samples)
  147. {
  148.     SETUP_SAMPLES(32, n * 4);
  149.     for (i = 0; i < n; ++i) {
  150.     samples[i] = (*p << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
  151.     p += 4;
  152.     }
  153.     return 0;
  154. }
  155.  
  156. private int (*const fn_get_samples[]) (P3(const gs_function_Sd_t * pfn,
  157.                       ulong offset, uint * samples)) =
  158. {
  159.     0, fn_gets_1, fn_gets_2, 0, fn_gets_4, 0, 0, 0,
  160.     fn_gets_8, 0, 0, 0, fn_gets_12, 0, 0, 0,
  161.     fn_gets_16, 0, 0, 0, 0, 0, 0, 0,
  162.     fn_gets_24, 0, 0, 0, 0, 0, 0, 0,
  163.     fn_gets_32
  164. };
  165.  
  166. /* Calculate a result by multilinear interpolation. */
  167. private void
  168. fn_interpolate_linear(const gs_function_Sd_t *pfn, const float *fparts,
  169.          const ulong *factors, float *samples, ulong offset, int m)
  170. {
  171.     int j;
  172.  
  173. top:
  174.     if (m == 0) {
  175.     uint sdata[max_Sd_n];
  176.  
  177.     (*fn_get_samples[pfn->params.BitsPerSample])(pfn, offset, sdata);
  178.     for (j = pfn->params.n - 1; j >= 0; --j)
  179.         samples[j] = sdata[j];
  180.     } else {
  181.     float fpart = *fparts++;
  182.     float samples1[max_Sd_n];
  183.  
  184.     if (is_fzero(fpart)) {
  185.         ++factors;
  186.         --m;
  187.         goto top;
  188.     }
  189.     fn_interpolate_linear(pfn, fparts, factors + 1, samples,
  190.                   offset, m - 1);
  191.     fn_interpolate_linear(pfn, fparts, factors + 1, samples1,
  192.                   offset + *factors, m - 1);
  193.     for (j = pfn->params.n - 1; j >= 0; --j)
  194.         samples[j] += (samples1[j] - samples[j]) * fpart;
  195.     }
  196. }
  197.  
  198. /* Evaluate a Sampled function. */
  199. private int
  200. fn_Sd_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
  201. {
  202.     const gs_function_Sd_t *pfn = (const gs_function_Sd_t *)pfn_common;
  203.     int bps = pfn->params.BitsPerSample;
  204.     ulong offset = 0;
  205.     int i;
  206.     float encoded[max_Sd_m];
  207.     ulong factors[max_Sd_m];
  208.     float samples[max_Sd_n];
  209.  
  210.     /* Encode the input values. */
  211.  
  212.     for (i = 0; i < pfn->params.m; ++i) {
  213.     float d0 = pfn->params.Domain[2 * i],
  214.         d1 = pfn->params.Domain[2 * i + 1];
  215.     float arg = in[i], enc;
  216.  
  217.     if (arg < d0)
  218.         arg = d0;
  219.     else if (arg > d1)
  220.         arg = d1;
  221.     if (pfn->params.Encode) {
  222.         float e0 = pfn->params.Encode[2 * i];
  223.         float e1 = pfn->params.Encode[2 * i + 1];
  224.  
  225.         enc = (arg - d0) * (e1 - e0) / (d1 - d0) + e0;
  226.         if (enc < 0)
  227.         encoded[i] = 0;
  228.         else if (enc >= pfn->params.Size[i] - 1)
  229.         encoded[i] = pfn->params.Size[i] - 1;
  230.         else
  231.         encoded[i] = enc;
  232.     } else {
  233.         /* arg is guaranteed to be in bounds, ergo so is enc */
  234.         encoded[i] = (arg - d0) * (pfn->params.Size[i] - 1) / (d1 - d0);
  235.     }
  236.     }
  237.  
  238.     /* Look up and interpolate the output values. */
  239.  
  240.     {
  241.     ulong factor = bps * pfn->params.n;
  242.  
  243.     for (i = 0; i < pfn->params.m; factor *= pfn->params.Size[i++]) {
  244.         int ipart = (int)encoded[i];
  245.  
  246.         offset += (factors[i] = factor) * ipart;
  247.         encoded[i] -= ipart;
  248.     }
  249.     }
  250.     /****** LINEAR INTERPOLATION ONLY ******/
  251.     fn_interpolate_linear(pfn, encoded, factors, samples, offset,
  252.               pfn->params.m);
  253.  
  254.     /* Encode the output values. */
  255.  
  256.     for (i = 0; i < pfn->params.n; ++i) {
  257.     float d0, d1, r0, r1, value;
  258.  
  259.     if (pfn->params.Range)
  260.         r0 = pfn->params.Range[2 * i], r1 = pfn->params.Range[2 * i + 1];
  261.     else
  262.         r0 = 0, r1 = (1 << bps) - 1;
  263.     if (pfn->params.Decode)
  264.         d0 = pfn->params.Decode[2 * i], d1 = pfn->params.Decode[2 * i + 1];
  265.     else
  266.         d0 = r0, d1 = r1;
  267.  
  268.     value = samples[i] * (d1 - d0) / ((1 << bps) - 1) + d0;
  269.     if (value < r0)
  270.         out[i] = r0;
  271.     else if (value > r1)
  272.         out[i] = r1;
  273.     else
  274.         out[i] = value;
  275.     }
  276.  
  277.     return 0;
  278. }
  279.  
  280. /* Test whether a Sampled function is monotonic. */
  281. private int
  282. fn_Sd_is_monotonic(const gs_function_t * pfn_common,
  283.            const float *lower, const float *upper,
  284.            gs_function_effort_t effort)
  285. {
  286.     const gs_function_Sd_t *const pfn =
  287.     (const gs_function_Sd_t *)pfn_common;
  288.     float d0 = pfn->params.Domain[0], d1 = pfn->params.Domain[1];
  289.     float v0 = lower[0], v1 = upper[0];
  290.     float e0, e1, w0, w1;
  291.     float r0[max_Sd_n], r1[max_Sd_n];
  292.     int code, i, result;
  293.  
  294.     /*
  295.      * Testing this in general is very time-consuming, so we don't bother.
  296.      * However, we do implement it correctly for one special case that is
  297.      * important in practice: for 1-input functions when the lower and
  298.      * upper values are in the same sample cell.
  299.      */
  300.     if (pfn->params.m > 1)
  301.     return gs_error_undefined;
  302.     if (lower[0] > pfn->params.Domain[1] ||
  303.     upper[0] < pfn->params.Domain[0]
  304.     )
  305.     return gs_error_rangecheck;
  306.     if (pfn->params.n > sizeof(int) * 4 - 1)
  307.     return 0;        /* can't represent result */
  308.     if (pfn->params.Encode)
  309.     e0 = pfn->params.Encode[0], e1 = pfn->params.Encode[1];
  310.     else
  311.     e0 = 0, e1 = pfn->params.Size[0];
  312.     w0 = (v0 - d0) * (e1 - e0) / (d1 - d0) + e0;
  313.     if (w0 < 0)
  314.     w0 = 0;
  315.     else if (w0 >= pfn->params.Size[0] - 1)
  316.     w0 = pfn->params.Size[0] - 1;
  317.     w1 = (v1 - d0) * (e1 - e0) / (d1 - d0) + e0;
  318.     if (w1 < 0)
  319.     w1 = 0;
  320.     else if (w1 >= pfn->params.Size[0] - 1)
  321.     w1 = pfn->params.Size[0] - 1;
  322.     if ((int)w0 != (int)w1)
  323.     return gs_error_undefined; /* not in the same sample */
  324.     code = gs_function_evaluate(pfn_common, lower, r0);
  325.     if (code < 0)
  326.     return code;
  327.     gs_function_evaluate(pfn_common, upper, r1);
  328.     if (code < 0)
  329.     return code;
  330.     for (i = 0, result = 0; i < pfn->params.n; ++i) {
  331.     double diff = r1[i] - r0[i];
  332.  
  333.     result |=
  334.         (diff < 0 ? FN_MONOTONIC_DECREASING :
  335.          diff > 0 ? FN_MONOTONIC_INCREASING :
  336.          FN_MONOTONIC_DECREASING | FN_MONOTONIC_INCREASING) <<
  337.         (2 * i);
  338.     }
  339.     return result;
  340. }
  341.  
  342. /* Return Sampled function information. */
  343. private void
  344. fn_Sd_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
  345. {
  346.     const gs_function_Sd_t *const pfn =
  347.     (const gs_function_Sd_t *)pfn_common;
  348.     long size;
  349.     int i;
  350.  
  351.     gs_function_get_info_default(pfn_common, pfi);
  352.     pfi->DataSource = &pfn->params.DataSource;
  353.     for (i = 0, size = 1; i < pfn->params.m; ++i)
  354.     size *= pfn->params.Size[i];
  355.     pfi->data_size =
  356.     (size * pfn->params.n * pfn->params.BitsPerSample + 7) >> 3;
  357. }
  358.  
  359. /* Write Sampled function parameters on a parameter list. */
  360. private int
  361. fn_Sd_get_params(const gs_function_t *pfn_common, gs_param_list *plist)
  362. {
  363.     const gs_function_Sd_t *const pfn =
  364.     (const gs_function_Sd_t *)pfn_common;
  365.     int ecode = fn_common_get_params(pfn_common, plist);
  366.     int code;
  367.  
  368.     if (pfn->params.Order != 1) {
  369.     if ((code = param_write_int(plist, "Order", &pfn->params.Order)) < 0)
  370.         ecode = code;
  371.     }
  372.     if ((code = param_write_int(plist, "BitsPerSample",
  373.                 &pfn->params.BitsPerSample)) < 0)
  374.     ecode = code;
  375.     if (pfn->params.Encode) {
  376.     if ((code = param_write_float_values(plist, "Encode",
  377.                          pfn->params.Encode,
  378.                          2 * pfn->params.m, false)) < 0)
  379.         ecode = code;
  380.     }
  381.     if (pfn->params.Decode) {
  382.     if ((code = param_write_float_values(plist, "Decode",
  383.                          pfn->params.Decode,
  384.                          2 * pfn->params.n, false)) < 0)
  385.         ecode = code;
  386.     }
  387.     if (pfn->params.Size) {
  388.     if ((code = param_write_int_values(plist, "Size", pfn->params.Size,
  389.                        pfn->params.m, false)) < 0)
  390.         ecode = code;
  391.     }
  392.     return ecode;
  393. }
  394.  
  395. /* Free the parameters of a Sampled function. */
  396. void
  397. gs_function_Sd_free_params(gs_function_Sd_params_t * params, gs_memory_t * mem)
  398. {
  399.     gs_free_const_object(mem, params->Size, "Size");
  400.     gs_free_const_object(mem, params->Decode, "Decode");
  401.     gs_free_const_object(mem, params->Encode, "Encode");
  402.     fn_common_free_params((gs_function_params_t *) params, mem);
  403. }
  404.  
  405. /* Allocate and initialize a Sampled function. */
  406. int
  407. gs_function_Sd_init(gs_function_t ** ppfn,
  408.           const gs_function_Sd_params_t * params, gs_memory_t * mem)
  409. {
  410.     static const gs_function_head_t function_Sd_head = {
  411.     function_type_Sampled,
  412.     {
  413.         (fn_evaluate_proc_t) fn_Sd_evaluate,
  414.         (fn_is_monotonic_proc_t) fn_Sd_is_monotonic,
  415.         (fn_get_info_proc_t) fn_Sd_get_info,
  416.         (fn_get_params_proc_t) fn_Sd_get_params,
  417.         (fn_free_params_proc_t) gs_function_Sd_free_params,
  418.         fn_common_free
  419.     }
  420.     };
  421.     int code;
  422.     int i;
  423.  
  424.     *ppfn = 0;            /* in case of error */
  425.     code = fn_check_mnDR((const gs_function_params_t *)params,
  426.              params->m, params->n);
  427.     if (code < 0)
  428.     return code;
  429.     if (params->m > max_Sd_m)
  430.     return_error(gs_error_limitcheck);
  431.     switch (params->Order) {
  432.     case 0:        /* use default */
  433.     case 1:
  434.     case 3:
  435.         break;
  436.     default:
  437.         return_error(gs_error_rangecheck);
  438.     }
  439.     switch (params->BitsPerSample) {
  440.     case 1:
  441.     case 2:
  442.     case 4:
  443.     case 8:
  444.     case 12:
  445.     case 16:
  446.     case 24:
  447.     case 32:
  448.         break;
  449.     default:
  450.         return_error(gs_error_rangecheck);
  451.     }
  452.     for (i = 0; i < params->m; ++i)
  453.     if (params->Size[i] <= 0)
  454.         return_error(gs_error_rangecheck);
  455.     {
  456.     gs_function_Sd_t *pfn =
  457.         gs_alloc_struct(mem, gs_function_Sd_t, &st_function_Sd,
  458.                 "gs_function_Sd_init");
  459.  
  460.     if (pfn == 0)
  461.         return_error(gs_error_VMerror);
  462.     pfn->params = *params;
  463.     if (params->Order == 0)
  464.         pfn->params.Order = 1;    /* default */
  465.     pfn->head = function_Sd_head;
  466.     pfn->head.is_monotonic =
  467.         fn_domain_is_monotonic((gs_function_t *)pfn, EFFORT_MODERATE);
  468.     *ppfn = (gs_function_t *) pfn;
  469.     }
  470.     return 0;
  471. }
  472.